/************************************************************************

								Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
  						 bitmap_layer.cpp

	$Header: /resource_editor/bitmap_group.cpp $

	$NoKeywords: $

 ************************************************************************/

// kill the 255+ character identifier warning.  Templates tend to exceed that easily.
#include "precompiled.h"
#pragma warning( disable: 4786 )

#include "bitmap_group.h"

#include "binary_find.h"
#include "pixel_24.h"
#include "progress_handler.h"
#include "streambuf_operators.h"

char const t_resource_traits<t_bitmap_group_24>::prefix[] = "layers";

char const t_resource_traits<t_bitmap_group_24>::extension[] = "psd";


// --------------------------------------------------------
// body of t_bitmap_group
// --------------------------------------------------------
t_screen_rect t_bitmap_group_24::get_rect() const
{
    const_iterator index = begin();
	t_screen_rect  result(0,0,0,0);
	
	while (index != end())
	{
		if (result.width() == 0)
			result = index->get_rect();
		else if (index->get_rect().width() > 0)
	        result = get_extent( result, index->get_rect() );
		index++;
	}
    return result;
}

// --------------------------------------------------------
// body of t_bitmap_group
// --------------------------------------------------------
void t_bitmap_group_24::offset( t_screen_point delta )
{
    iterator index = begin();

	while (index != end())
	{
		index->offset( delta );
		index++;
	}
}

// --------------------------------------------------------
// function object to sort bitmaps by layer name
// --------------------------------------------------------
namespace 
{
	class t_sort_by_name
	{
	public:
		bool operator()( t_bitmap_layer_24 const& left, t_bitmap_layer_24 const& right )
		{
			return stricmp( left.get_name().c_str(), right.get_name().c_str() ) < 0;
		}
	};

	class t_find_operator
	{
	public:
		bool operator()( t_shared_layer_ptr const& left, const char* name )
		{
			return stricmp( left->get_name().c_str(), name ) < 0;
		}
	};
};

// --------------------------------------------------------
// group of 24-bit palette bitmap layers
// --------------------------------------------------------
bool t_bitmap_group_24::read( std::streambuf& buffer, t_progress_handler* handler )
{
	iterator index;

	resize( get<t_uint16>( buffer ) );
	if (handler != 0)
		handler->increment( sizeof(t_uint16) );
	for (index = begin(); index != end(); index++)
		if (!index->read( buffer, handler ))
			return false;
	std::sort( begin(), end(), t_sort_by_name() );
	return true;
}

// --------------------------------------------------------
// group of 24-bit palette bitmap layers
// --------------------------------------------------------
bool t_bitmap_group_24::write( std::streambuf& buffer ) const
{
	const_iterator index;

	put<t_uint16>( buffer, size() );
	for (index = begin(); index != end(); index++)
		if (!index->write( buffer ))
			return false;
	return true;
}

// --------------------------------------------------------
// group of 16-bit palette bitmap layers
// --------------------------------------------------------
t_bitmap_group::t_bitmap_group( t_bitmap_group_24 const& source )
{
	t_bitmap_group_24::const_iterator index;

	reserve( source.size() );
	for (index = source.begin(); index != source.end(); index++)
		push_back( new t_paletted_16_layer( *index ) );
}

// --------------------------------------------------------
// group of 16-bit palette bitmap layers
// --------------------------------------------------------
t_bitmap_group::~t_bitmap_group()
{
}

// --------------------------------------------------------
// body of t_bitmap_group
// --------------------------------------------------------
t_screen_rect t_bitmap_group::get_rect() const
{
    const_iterator index = begin();
    t_screen_rect  result = (*index)->get_rect();

	while (index != end())
	{
        result = get_extent( result, (*index)->get_rect() );
		index++;
	}
    return result;
}

// --------------------------------------------------------
// body of t_bitmap_group
// --------------------------------------------------------
void t_bitmap_group::offset( t_screen_point delta )
{
    iterator index = begin();

	while (index != end())
	{
		index->get()->offset( delta );
		index++;
	}
}


// --------------------------------------------------------
// determine max alpha depth for entire group
// --------------------------------------------------------
int t_bitmap_group::get_alpha_depth() const
{
	int            result = 0;
    const_iterator index = begin();
    t_screen_rect  rect = (*index)->get_rect();

	while (index != end())
	{
		if (result == 0 && (*index)->get_rect() != rect)
			result = 1;
		if ( (*index)->get_alpha_depth() > result )
		{
			result = (*index)->get_alpha_depth();
			if (result == 4)
				return 4;
		}
		index++;
	}
    return result;
}

// --------------------------------------------------------
// find a layer in the group
// --------------------------------------------------------
t_bitmap_layer * t_bitmap_group::find( std::string const& name )
{
	iterator index = binary_find( begin(), size(), name.c_str(), t_find_operator() );

	if (index == end())
		return 0;

	if (stricmp((*index)->get_name().c_str(), name.c_str() ) == 0)
		return index->get();
	return 0;
}

t_bitmap_layer const * t_bitmap_group::find( std::string const& name ) const
{
	const_iterator index = binary_find( begin(), size(), name.c_str(), t_find_operator() );

	if (index == end())
		return 0;

	if (stricmp((*index)->get_name().c_str(), name.c_str() ) == 0)
		return index->get();
	return 0;
}

// --------------------------------------------------------
// find a layer in the group
// --------------------------------------------------------
t_bitmap_group::iterator t_bitmap_group::find_iterator( std::string const& name )
{
	iterator index = binary_find( begin(), size(), name.c_str(), t_find_operator() );

	if (index == end())
		return index;

	if (stricmp((*index)->get_name().c_str(), name.c_str() ) == 0)
		return index;
	return end();
}

// --------------------------------------------------------
// find a layer in the group
// --------------------------------------------------------
t_bitmap_group::const_iterator t_bitmap_group::find_iterator( std::string const& name ) const
{
	const_iterator index = binary_find( begin(), size(), name.c_str(), t_find_operator() );

	if (index == end())
		return index;

	if (stricmp((*index)->get_name().c_str(), name.c_str() ) == 0)
		return index;
	return end();
}
